var SEA = require('./root');
var shim = require('./shim');
var S = require('./settings');
var sha256hash = require('./sha256');

SEA.sign =
  SEA.sign ||
  (async (data, pair, cb) => {
    try {
      if (
        data &&
        data.slice &&
        'SEA{' === data.slice(0, 4) &&
        '"m":' === data.slice(4, 8)
      ) {
        // TODO: This would prevent pair2 signing pair1's signature.
        // So we may want to change this in the future.
        // but for now, we want to prevent duplicate double signature.
        if (cb) {
          try {
            cb(data);
          } catch (e) {
            // FIXME: Throw when not the expected error
            //if (e !== TODO) throw e;
            console.log(
              'If this error occured during normal operation validate it here',
              e
            );
          }
        }
        return data;
      }
      const pub = pair.pub;
      const priv = pair.priv;
      const jwk = S.jwk(pub, priv);
      const msg = JSON.stringify(data);
      const hash = await sha256hash(msg);
      const sig = await (shim.ossl || shim.subtle)
        .importKey('jwk', jwk, S.ecdsa.pair, false, ['sign'])
        .then(key =>
          (shim.ossl || shim.subtle).sign(
            S.ecdsa.sign,
            key,
            new Uint8Array(hash)
          )
        ); // privateKey scope doesn't leak out from here!
      const r =
        'SEA' +
        JSON.stringify({
          m: msg,
          s: shim.Buffer.from(sig, 'binary').toString('utf8')
        });

      if (cb) {
        try {
          cb(r);
        } catch (e) {
          // FIXME: Throw when not the expected error
          //if (e !== TODO) throw e;
          console.log(
            'If this error occured during normal operation validate it here',
            e
          );
        }
      }
      return r;
    } catch (e) {
      // FIXME: Throw when not the expected error
      //if (e !== TODO) throw e;
      console.log(
        'If this error occured during normal operation validate it here',
        e
      );
      SEA.err = e;
      if (cb) {
        cb();
      }
      return;
    }
  });

module.exports = SEA.sign;
